﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.ComponentModel;

namespace MitutoyoRS232DataInputTool
{
    public class ViewModel : INotifyPropertyChanged
    {
        RS232InputTool tool = new RS232InputTool();

        public ViewModel()
        {
            tool.DataReceived += new EventHandler<DataEventArgs>(tool_DataReceived);
            tool.PropertyChanged += new PropertyChangedEventHandler(tool_PropertyChanged);

            LoadSettings();
        }

        ~ViewModel()
        {
            SaveSettings();
        }

        private void LoadSettings()
        {
            SelectedPort = Properties.Settings.Default["ComPort"] as string;
            EmulateKeyboard = (Properties.Settings.Default["EmulateKeyboard"] as bool?) ?? false;
            BackspacePreviousData = (Properties.Settings.Default["BackspaceOverPreviousData"] as bool?) ?? false;
            AlwaysOnTop = (Properties.Settings.Default["AlwaysOnTop"] as bool?) ?? false;
            Prepend = Properties.Settings.Default["Prepend"] as string;
            Append = Properties.Settings.Default["Append"] as string;
            IntermittentPrepend = Properties.Settings.Default["IntermittentPrepend"] as string;
            IntermittentAppend = Properties.Settings.Default["IntermittentAppend"] as string;
            IntermittentEvery = (Properties.Settings.Default["IntermittentEvery"] as int?) ?? 3;
            HasIntermittent = (Properties.Settings.Default["HasIntermittent"] as bool?) ?? false;
        }

        private void SaveSettings()
        {
            Properties.Settings.Default["ComPort"] = SelectedPort;
            Properties.Settings.Default["EmulateKeyboard"] = EmulateKeyboard;
            Properties.Settings.Default["BackspaceOverPreviousData"] = BackspacePreviousData;
            Properties.Settings.Default["AlwaysOnTop"] = AlwaysOnTop;
            Properties.Settings.Default["Prepend"] = Prepend;
            Properties.Settings.Default["Append"] = Append;
            Properties.Settings.Default["IntermittentPrepend"] = IntermittentPrepend;
            Properties.Settings.Default["IntermittentAppend"] = IntermittentAppend;
            Properties.Settings.Default["IntermittentEvery"] = IntermittentEvery;
            Properties.Settings.Default["HasIntermittent"] = HasIntermittent;
            Properties.Settings.Default.Save();
        }

        void tool_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsConnected":
                    FirePropertyChanged("IsConnected");
                    break;
            }
        }

        private string lastDataRead;
        public string LastDataRead
        {
            get
            {
                return lastDataRead;
            }
            set
            {
                lastDataRead = value;
                FirePropertyChanged("LastDataRead");        
            }
        }

        private int counter = 0;
        public int Counter
        {
            get { return counter; }
            set
            {
                if (counter != value)
                {
                    counter = value;
                    FirePropertyChanged("Counter");
                }
            }
        }

        private bool alwaysOnTop;
        public bool AlwaysOnTop
        {
            get { return alwaysOnTop; }
            set
            {
                if (alwaysOnTop != value)
                {
                    alwaysOnTop = value;
                    FirePropertyChanged("AlwaysOnTop");
                }
            }
        }
        
        void tool_DataReceived(object sender, DataEventArgs e)
        {

            LastDataRead = e.NumberRead.ToString();
            if (EmulateKeyboard)
            {
                string prepend = "";
                string append = "";

                if (BackspacePreviousData && LastDataRead != null)
                {
                    foreach (char c in LastDataRead)
                    {
                        prepend += "{BS}";
                    }
                }

                prepend += Prepend;
                append += Append;

                if (HasIntermittent && (++Counter % IntermittentEvery) == 0)
                {
                    prepend += IntermittentPrepend;
                    append += IntermittentAppend;
                }

                SendKeys.SendWait(prepend + e.NumberRead.ToString() + append);
            }
        }

        private bool hasIntermittent;

        public bool HasIntermittent
        {
            get { return hasIntermittent; }
            set
            {
                if (hasIntermittent != value)
                {
                    hasIntermittent = value;
                    FirePropertyChanged("HasIntermittent");
                }
            }
        }

        private int _IntermittentEvery;

        public int IntermittentEvery
        {
            get { return _IntermittentEvery; }
            set
            {
                if (_IntermittentEvery != value)
                {
                    _IntermittentEvery = value;
                    FirePropertyChanged("IntermittentEvery");
                }
            }
        }

        private string _IntermittentPrepend;

        public string IntermittentPrepend
        {
            get { return _IntermittentPrepend; }
            set
            {
                if (_IntermittentPrepend != value)
                {
                    _IntermittentPrepend = value;
                    FirePropertyChanged("IntermittentPrepend");
                }
            }
        }

        private string _IntermittentAppend;

        public string IntermittentAppend
        {
            get { return _IntermittentAppend; }
            set
            {
                if (_IntermittentAppend != value)
                {
                    _IntermittentAppend = value;
                    FirePropertyChanged("IntermittentAppend");
                }
            }
        }



        private string selectedPort;
        public String SelectedPort
        {
            get { return selectedPort; }
            set
            {
                selectedPort = value;
                if (tool.IsConnected)
                {
                    tool.Disconnect();
                }
                if (selectedPort != null && selectedPort != "")
                {
                    try
                    {
                        tool.Connect(selectedPort);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Error connecting to '" + selectedPort + "': " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                    }
                }
            }
        }

        private bool emulateKeyboard;
        public bool EmulateKeyboard
        {
            get {
                return emulateKeyboard;
            }
            set
            {
                emulateKeyboard = value;
                FirePropertyChanged("EmulateKeyboard");
            }
        }

        public void GetData()
        {
            tool.TriggerDataRead();
        }

        public String[] AvailablePorts
        {
            get
            {
                return SerialPort.GetPortNames();
            }
        }

        private string[] sendKeyOptions = new string[] { "", "{TAB}", "{ENTER}", "{LEFT}", "{RIGHT}", "{UP}", "{DOWN}", "{BACKSPACE}", "{DELETE}" };
        public String[] PrependOptions
        {
            get
            {
                return sendKeyOptions;
            }
        }

        private string prepend;
        public string Prepend
        {
            get
            {
                return prepend;
            }
            set
            {
                prepend = value;
                FirePropertyChanged("Prepend");
            }
        }

        private string append = "{ENTER}";
        public string Append
        {
            get { return append; }
            set
            {
                append = value;
                FirePropertyChanged("Append");
            }
        }

        public String[] AppendOptions
        {
            get
            {
                return sendKeyOptions;
            }
        }

        public bool IsConnected {
            get
            {
                return tool.IsConnected;
            }
        }

        public bool BackspacePreviousData { get; set; }

        #region NotifyPropertyChanged

        /// <summary>
        /// Provides notification when a property's value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        void FirePropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

    }
}
